package jp.sourceforge.akjrcp.psp.imageconvert;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.commons.ui.FileDirChoicer;
import jp.sourceforge.akjrcp.commons.ui.AbstractFileDirChoicer.FileStatusChangeEvent;
import jp.sourceforge.akjrcp.commons.ui.AbstractFileDirChoicer.FileStatusChangeListener;
import jp.sourceforge.akjrcp.commons.ui.widget.WidgetBuilder;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUtils;
import jp.sourceforge.akjrcp.psp.PSPUtils;
import jp.sourceforge.akjrcp.ui.GenericParameters;
import jp.sourceforge.akjrcp.ui.LayoutDataBuilder;
import jp.sourceforge.akjrcp.ui.param.ParamBoolean;
import jp.sourceforge.akjrcp.ui.param.ParamCheckGroup;
import jp.sourceforge.akjrcp.ui.param.ParamCombo;
import jp.sourceforge.akjrcp.ui.param.ParamItem;
import jp.sourceforge.akjrcp.ui.param.ParamItemActionListener;
import jp.sourceforge.akjrcp.ui.param.ParamRadioComposite;
import jp.sourceforge.akjrcp.ui.param.ParamRadioContainer;
import jp.sourceforge.akjrcp.ui.param.ParamScale;
import jp.sourceforge.akjrcp.ui.param.ParamTab;
import jp.sourceforge.akjrcp.ui.param.ParamText;
import jp.sourceforge.akjrcp.ui.param.ParamTextArea;
import jp.sourceforge.akjrcp.util.ExecutingControler;
import jp.sourceforge.akjrcp.util.FileNameUtils;
import jp.sourceforge.akjrcp.util.ProgressMonitorUtils;
import jp.sourceforge.akjrcp.util.StatusBarUtils;
import jp.sourceforge.akjrcp.util.ExecutingControler.ExecutingControlButton;
import jp.sourceforge.akjrcp.util.image.ImageUtils;
import jp.sourceforge.akjrcp.videotools.dvdtoxvid.CheckToRadio;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.part.ViewPart;


public class PSPImageImportViewer extends ViewPart {
	public static Log log=LogFactory.getLog(PSPImageImportViewer.class);
	
	public static final String ID = PSPImageImportViewer.class.getName();
	
	
	private FileDirChoicer inputDirChooser;

	private FileDirChoicer outputDirChooser;
	private PSPImageImportExecute pspImageImportExecute;
	
	private ParamRadioComposite imageType;

	//private CheckToRadio convertModeRadioControler;



	private ParamRadioComposite splitWidthSize;

	private ParamTab modeTab;

//	private Button importJpeg;

//	private Button importPng;

//	private Button importGif;

	
	private Button splitTypePixel;
	@SuppressWarnings("unused") //read only
	private Button splitTypeNum;

	private ParamBoolean supportDoubleSizeCheck;
	private ParamBoolean keepAspectCheck;
	
	private ParamScale jpegQualityScale;

	private ParamRadioComposite turnTypeRadio;

	private ParamRadioComposite turnSize;

	private ParamRadioComposite fitSizeSizeRadio;

	private ParamRadioComposite fitWidthSizeRadio;

	private ParamRadioComposite fitHeightSizeRadio;

	private ParamCombo minSupportWidthCombo;
	private ParamCombo maxSplitCombo;
	private ParamCombo overWrapSizeCombo;
	
	private ParamCheckGroup importImages;
	private ParamCsvUpdater paramCsvUpdater=new ParamCsvUpdater();
	public void createPartControl(Composite parent) {
		pspImageImportExecute = new PSPImageImportExecute();
		
		parent.setLayout(new GridLayout(1,false));
		/*
		Composite labelComposite=new LabelComposite(parent,SWT.NULL,Messages.getString("pspimage.import_image"));
		labelComposite.setLayout(new GridLayout(4,true));
		*/
		
		importImages=new ParamCheckGroup(parent,SWT.NULL,"import_image",Messages.getString("pspimage.import_image"),new String[]{"JPEG","PNG","GIF"},3);
		importImages.setValue("JPEG+PNG+GIF");//initial value
		paramCsvUpdater.add(importImages);
		
		//jpegQualityScale.setHeaderText(Messages.getString("pspimage.jpeg_quality")+" ");
		//jpegQualityScale.setFooterText(" %");
		//jpegQualityScale.setLayoutData(new GridData(GridData.FILL_HORIZONTAL),LayoutDataBuilder.hintGridData(100, 0),new GridData(GridData.FILL_HORIZONTAL));
		
		//convertModeRadioControler = new CheckToRadio();
		//Composite modeList=new Composite(parent,SWT.NULL);
		//modeList.setLayout(new GridLayout(3,false));
		
		Group export=WidgetBuilder.createFillLayoutGroup(parent,SWT.NULL);
		export.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
		export.setText(Messages.getString("pspimage.convert_type"));
		modeTab = new ParamTab(export,SWT.NULL,"convert_type");
		Composite splitMode=modeTab.createGridLayoutTab(Messages.getString("pspimage.split"), SWT.NULL);
		paramCsvUpdater.add(modeTab);
		
		//LabeledCheckedGrup splitMode=new LabeledCheckedGrup(tab,SWT.NULL,"split",convertModeRadioControler);
		//item.setControl(splitMode);
		//Composite tabComposite
		//splitMode.setLayoutData(LayoutDataBuilder.fillBothGridData());
		//TODO paramValue to store last selection
		
		ParamRadioContainer convertTypeRadios=new ParamRadioContainer("convertType");
		paramCsvUpdater.add(convertTypeRadios);
		
		Composite splitType=WidgetBuilder.createGridLayoutComposite(splitMode, SWT.NULL, 4, false);
		splitTypeNum = convertTypeRadios.createButton(splitType, SWT.NULL, "","splitTypeNum");
		//splitTypeNum.setSelection(true); //todo keep last settings
		
		maxSplitCombo = new ParamCombo(new BothLabelComposite(splitType,SWT.NULL,Messages.getString("pspimage.min_split"),"").getComposite(),SWT.NULL,"maxSplitCombo","",new String[]{"3","4","5"});
		paramCsvUpdater.add(maxSplitCombo);
		maxSplitCombo.setValue("4");
		
		splitTypePixel = convertTypeRadios.createButton(splitType, SWT.NULL, "","splitTypePixel");
		
		overWrapSizeCombo = new ParamCombo(new BothLabelComposite(splitType,SWT.NULL,Messages.getString("pspimage.overwrap"),"%").getComposite(),SWT.NULL,"overWrapSize","",new String[]{"50","33","25","10","5","0"});
		paramCsvUpdater.add(overWrapSizeCombo);
		overWrapSizeCombo.setValue("25");
		
		
		Composite width_keep=WidgetBuilder.createGridLayoutComposite(splitMode, SWT.NONE,2,false);
		
		LabelComposite w_v=new LabelComposite(width_keep,SWT.NULL,Messages.getString("pspimage.width"));
		splitWidthSize = new ParamRadioComposite(w_v,SWT.NULL,"splitWidthSize",new String[]{"240","480","720","960","1440","1920"},new String[]{"240","480","720","960","1440","1920"},6);
		paramCsvUpdater.add(splitWidthSize);
		splitWidthSize.setValue("480");
		
		keepAspectCheck=new ParamBoolean(width_keep,SWT.NULL,"keep_aspect",Messages.getString("pspimage.keep_aspect"));
		paramCsvUpdater.add(keepAspectCheck);
		keepAspectCheck.setBoolean(true);
		
		
		
		
		Composite doubleContainer=WidgetBuilder.createGridLayoutComposite(splitMode, SWT.NULL, 2, false);
		//supportDoubleSizeCheck = WidgetBuilder.createCheckButton(doubleContainer, Messages.getString("pspimage.support_double"));
		supportDoubleSizeCheck=new ParamBoolean(doubleContainer,SWT.NULL,"support_double",Messages.getString("pspimage.support_double"));
		paramCsvUpdater.add(supportDoubleSizeCheck);
		supportDoubleSizeCheck.setBoolean(true);
		
		minSupportWidthCombo = new ParamCombo(doubleContainer,SWT.NULL,"minDoubleWidth",Messages.getString("pspimage.min_double_width"),new String[]{"800","1000","1300","1800","2600"});
		paramCsvUpdater.add(minSupportWidthCombo);
		minSupportWidthCombo.setValue("1300");
		Composite turnMode=modeTab.createGridLayoutTab(Messages.getString("pspimage.turn"), SWT.NULL);
		turnMode.setLayoutData(LayoutDataBuilder.fillBothGridData());
		
		turnTypeRadio = new ParamRadioComposite(turnMode,SWT.NULL,"turnType",new String[]{"LEFT","RIGHT"},new String[]{Messages.getString("pspimage.left"),Messages.getString("pspimage.right")},2);
		paramCsvUpdater.add(turnTypeRadio);
		turnTypeRadio.setValue("RIGHT");
		turnSize = new ParamRadioComposite(turnMode,SWT.NULL,"turnSize",new String[]{"272x480","542x960"},new String[]{"272x480","542x960"},2);
		paramCsvUpdater.add(turnSize);
		turnSize.setValue("542x960");//default is double
		
		
		Composite fitSize=modeTab.createGridLayoutTab(Messages.getString("pspimage.fit_size"), SWT.NULL);
		fitSize.setLayoutData(LayoutDataBuilder.fillBothGridData());
		
		fitSizeSizeRadio = new ParamRadioComposite(fitSize,SWT.NULL,"fitSizeSize",new String[]{"320x240","480x272","960x542"},new String[]{"320x240","480x272","960x542"},3);
		paramCsvUpdater.add(fitSizeSizeRadio);
		fitSizeSizeRadio.setValue("480x272");
		
		Composite fitWidth=modeTab.createGridLayoutTab(Messages.getString("pspimage.fit_width"), SWT.NULL);
		fitWidth.setLayoutData(LayoutDataBuilder.fillBothGridData());
		fitWidthSizeRadio = new ParamRadioComposite(fitWidth,SWT.NULL,"fitWidthSize",new String[]{"240","480","960"},new String[]{"240","480","960"},3);
		fitWidthSizeRadio.setValue("480");
		paramCsvUpdater.add(fitWidthSizeRadio);
		
		Composite fitHeight=modeTab.createGridLayoutTab(Messages.getString("pspimage.fit_height"), SWT.NULL);
		
		fitHeight.setLayoutData(LayoutDataBuilder.fillBothGridData());
		
		fitHeightSizeRadio = new ParamRadioComposite(fitHeight,SWT.NULL,"fitHeightSize",new String[]{"136","272","544"},new String[]{"136","272","544"},3);
		paramCsvUpdater.add(fitHeightSizeRadio);
		fitHeightSizeRadio.setValue("272");
		
		FileSelected selectedListener=new FileSelected();
		inputDirChooser = new FileDirChoicer(parent,SWT.BORDER,FileDirChoicer.FILE_DIR,Messages.getString("pspimage.input"));
		inputDirChooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		inputDirChooser.addFileListChangeListener(selectedListener);
		inputDirChooser.setFilterExtensions(new String[]{"*.zip"});
		//export group
		Composite outputs=WidgetBuilder.createGridLayoutComposite(parent, SWT.BORDER, 2, false);
		outputs.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
		
		outputDirChooser = new FileDirChoicer(outputs,SWT.NULL,FileDirChoicer.DIR,Messages.getString("pspimage.output"));
		outputDirChooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		outputDirChooser.addFileListChangeListener(selectedListener);
		
		
		Button pspExport=WidgetBuilder.createButton(outputs, Messages.getString("pspimage.select_pspdir"));
		pspExport.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e) {
				setPSPDir();
			}});
		

		Composite exportType=new Composite(outputs,SWT.NULL);
		GridData exdata=new GridData(GridData.FILL_HORIZONTAL);
		exdata.horizontalSpan=2;
		exportType.setLayoutData(exdata);
		
		exportType.setLayout(new GridLayout(3,false));
		Label exportLabel=new Label(exportType,SWT.NULL);
		exportLabel.setText(Messages.getString("pspimage.export_type"));
		//TODO support PNG
		imageType=new ParamRadioComposite(exportType,SWT.NULL,"imageType",new String[]{"JPEG"},new String[]{"JPEG"},2);
		imageType.setValue("JPEG");
		paramCsvUpdater.add(imageType);
		
		jpegQualityScale = new ParamScale(exportType,SWT.NULL,"jpeg_quality",Messages.getString("pspimage.jpeg_quality"),1,90,100);
		jpegQualityScale.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
		jpegQualityScale.getScale().setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
		paramCsvUpdater.add(jpegQualityScale);
		
		
		//TODO set psp dir if exist
		
		//inputDirChooser.setFilePath("c:\\tmp\\naruto_comic");
		
		
		//inputDirChooser.setFilePath("c:\\tmp\\test.zip");
		//outputDirChooser.setFilePath("c:\\tmp\\img1");
		
		pspImageImportExecute.addControl(inputDirChooser);
		pspImageImportExecute.addControl(outputDirChooser);
		pspImageImportExecute.addControl(pspExport);
		
		ExecutingControlButton exec=new ExecutingControlButton(parent,SWT.NULL,pspImageImportExecute,
				Messages.getString("exec"),Messages.getString("cancel"));
		exec.setLayoutData(LayoutDataBuilder.hintGridData(100,40));
		
		pspImageImportExecute.updateControlSwitch();
		
		loadParameters(widgetKey);
		this.getSite().getPage().addPartListener(new ParamSaver());
		
		new DropMonitor(parent);
	}
	
	protected void setPSPDir() {
		File pspDir=PSPUtils.findPSPDrive();
		if(pspDir!=null){
			if(PSPUtils.existPictureFolder(pspDir)){
				outputDirChooser.setFile(new File(pspDir,PSPUtils.DIR_PICTURE));
				
			}else{
				boolean bool=MessageDialog.openQuestion(getSite().getShell(), Messages.getString("pspimage.make_picture"), Messages.getString("pspimage.can_i_make"));
				if(bool){
					boolean result=new File(pspDir,PSPUtils.DIR_PICTURE).mkdir();
					if(result){
						outputDirChooser.setFile(new File(pspDir,PSPUtils.DIR_PICTURE));
					}else{
						log.warn("make picture folder faild");
					}
				}
			}
			pspImageImportExecute.updateControlSwitch();
			StatusBarUtils.showStatusBar("");//clear
		}else{
			StatusBarUtils.showStatusBar(Messages.getString("pspimage.not_psp_connected"));//show info
		}
	}

	public class DropMonitor extends DropTargetAdapter {
		public DropMonitor(Composite controler){
			Transfer[] types = new Transfer[] { FileTransfer.getInstance() };

			int operations = DND.DROP_MOVE | DND.DROP_COPY;

			DropTarget target2 = new DropTarget(controler, operations);
			target2.setTransfer(types);

			target2.addDropListener(this);
		}
		public void dragEnter(DropTargetEvent event) {
			// log.infodrag enter:"+event.data);
		}

		public void dragOver(DropTargetEvent event) {
			// log.infodrag over:"+event.data);
		}

		public void drop(DropTargetEvent event) {
			//log.info("cancovert:"+isCanConvert());
					
			String files[] = (String[]) event.data;

			
			for (int i = 0; i < files.length; i++) {
				dropFile(files[i]);
				break;	//now firat 1 file only
			}
			
		}
	}
	
	public void dropFile(String path){
		inputDirChooser.setFilePath(path);
		if(outputDirChooser.getAbsoluteFilePath().equals("")){
			setPSPDir();
		}
		
		if(pspImageImportExecute.canExecute()){
			if(!pspImageImportExecute.isExecuting()){
				pspImageImportExecute.execute();
			}
		}
	}
	
	public class ParamCsvUpdater implements ParamItemActionListener{
		private String csv;
		protected List<ParamItem> paramList=new ArrayList<ParamItem>();
		public void paramItemModified(ParamItem item) {
			csv=GenericParameters.mapToCsv(getParameters());
		}
		public String getCsv() {
			return csv;
		}
		public void add(ParamItem item){
			paramList.add(item);
			item.setParamItemActionListener(this);
		}
		public List<ParamItem> getParamList() {
			return paramList;
		}
		public void setParamList(List<ParamItem> paramList) {
			this.paramList = paramList;
		}
		
	}
	
	public class LabeledCheckedGrup extends Composite{
		private Button checkButton;
		private Label label;
		private Composite container;
		private Group group;
		public LabeledCheckedGrup(Composite parent, int style,String labelText,CheckToRadio checkToRadio) {
			super(parent, style);
			this.setLayout(new FillLayout());
			group=new Group(this,SWT.NULL);
			group.setLayout(new GridLayout());
			Composite labels=new Composite(group,SWT.NULL);
			labels.setLayout(new GridLayout(2,false));
			labels.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
			checkButton=checkToRadio.createButton(labels, SWT.CHECK);
			checkButton.setData("label",labelText);
			label=new Label(labels,SWT.NULL);
			label.setForeground(new Color(null,0,0x46,0xd5));
			label.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
			label.setText(labelText);
			container=new Composite(group,SWT.NULL);
			container.setLayoutData(LayoutDataBuilder.fillBothGridData());
			container.setLayout(new GridLayout());//default layout
		}
		public Button getCheckButton() {
			return checkButton;
		}
		public void setCheckButton(Button checkButton) {
			this.checkButton = checkButton;
		}
		public Composite getContainer() {
			return container;
		}
		public void setContainer(Composite container) {
			this.container = container;
		}
		public Group getGroup() {
			return group;
		}
		public void setGroup(Group group) {
			this.group = group;
		}
		public Label getLabel() {
			return label;
		}
		public void setLabel(Label label) {
			this.label = label;
		}
		
	}
	
	public class LabelComposite extends Composite{
		private Label label;
		public LabelComposite(Composite parent, int style,String text) {
			super(parent, style);
			this.setLayout(new GridLayout(2,false));
			label=new Label(this,SWT.NULL);
			label.setText(text);
		}
		public Label getLabel() {
			return label;
		}
		public void setLabel(Label label) {
			this.label = label;
		}
		
	}
	
	public class BothLabelComposite extends Composite{
		private Label headerLabel;
		private Label footerLabel;
		private Composite composite;
		public Composite getComposite() {
			return composite;
		}
		public void setComposite(Composite composite) {
			this.composite = composite;
		}
		public Label getFooterLabel() {
			return footerLabel;
		}
		public void setFooterLabel(Label footerLabel) {
			this.footerLabel = footerLabel;
		}
		public Label getHeaderLabel() {
			return headerLabel;
		}
		public void setHeaderLabel(Label headerLabel) {
			this.headerLabel = headerLabel;
		}
		public BothLabelComposite(Composite parent, int style,String header,String footer) {
			super(parent, style);
			this.setLayout(new GridLayout(3,false));
			headerLabel=new Label(this,SWT.NULL);
			headerLabel.setText(header);
			composite=new Composite(this,SWT.NULL);
			composite.setLayout(new FillLayout());
			footerLabel=new Label(this,SWT.NULL);
			footerLabel.setText(footer);
		}
		
		
	}
	
	
	public void setFocus() {
		
	}
	private Composite createSplitComposite(Composite parent,int split,boolean same,Object data){
		Composite composite=new Composite(parent,SWT.NULL);
		composite.setLayout(new GridLayout(split,same));
		if(data!=null){
			composite.setLayoutData(data);
		}
		return composite;
	}
	private ParamTextArea createGridTextAreaGroup(Composite parent,String key,String label,Object data){
		/*Group group=new Group(parent,SWT.NULL);
		group.setText(label);
		group.setLayout(new FillLayout());
		group.setLayoutData(data);
		Text text=new Text(group,SWT.MULTI|SWT.V_SCROLL|SWT.H_SCROLL|SWT.BORDER);
		*/
		
		ParamTextArea text=new ParamTextArea(parent,SWT.NULL,key,label,ParamText.LAYOUT_FILL_BOTH);
		text.setLayoutData(data);
		return text;
	}
	
	private ParamText createLabeldText(Composite parent,String key,String label,Object data){
		ParamText text=new ParamText(parent,SWT.NULL,key,label,ParamText.LAYOUT_FILL_HORIZONTAL);
		if(data!=null){
			text.setLayoutData(data);
		}
		return text;
	}
	
	public class PSPImageImportExecute extends ExecutingControler{
		
		
		private String inputDirChooser_value;

		private String outputDirChooser_value;
		
		private int overWrapSize_value;
		private int imageWidth;
		private int imageHeight;
		private int mode;
		public static final int SPLIT=0;
		public static final int TURN=1;
		public static final int SIZE=2;
		public static final int WIDTH=3;
		public static final int HEIGHT=4;
		
		private SupportCancel supportCancel;
		private boolean convertJpeg;
		private boolean convertGif;
		private boolean convertPng;
		private IProgressMonitor monitor;
		private boolean isSplitTypePixel;
		private int splitNum_value;
		private boolean supportDouble;
		private float jpegQuality;
		private int turnType_value;
		private ImageChanger imageChanger;
		private int minDoubleSize;
		private boolean cancelChange;
		private boolean keepAspect;
		public void afterExecute() {
			
		}

		@Override
		public void beforeExecute() {
			pspImageImportExecute.updateControlSwitch();//for drop executing
			convertJpeg=false;
			convertPng=false;
			convertGif=false;
			cancelChange=false;
			String importImageValues[]=importImages.getSelectionValues();
			for (int i = 0; i < importImageValues.length; i++) {
				if(importImageValues[i].equals("JPEG")){
					convertJpeg=true;
				}
				if(importImageValues[i].equals("GIF")){
					convertGif=true;
				}
				if(importImageValues[i].equals("PNG")){
					convertPng=true;
				}
			}
			
			
			jpegQuality=(float)jpegQualityScale.getScale().getSelection()/100;
			//Button bt=convertModeRadioControler.getSelection();
			String label=modeTab.getValue();
			
			if(label.equals(Messages.getString("pspimage.split"))){
				mode=SPLIT;
				overWrapSize_value=toInt(overWrapSizeCombo.getValue(),90);
				splitNum_value=toInt(maxSplitCombo.getValue(),4);
				imageWidth=toInt(splitWidthSize.getValue(),480);
				isSplitTypePixel=splitTypePixel.getSelection();
				supportDouble=supportDoubleSizeCheck.getBoolean();
				ImageSplitter splitter=new ImageSplitter();
				splitter.setJpegQuality(jpegQuality);
				supportCancel=splitter;
				keepAspect=keepAspectCheck.getBoolean();
				double ratio=(double)imageWidth/480;	//480 is PSP default
				int h=272;
				
				if(keepAspect){
					h=(int) (ratio*272);	//272 is PSP default height
				}
				int overwrap=0;
				if(overWrapSize_value>0){
					overwrap=(int) (h*((double)overWrapSize_value/100));
				}
				
				minDoubleSize=toInt(minSupportWidthCombo.getValue(),1300);
				log.info("width="+imageWidth+" height="+h+" overwrap="+overwrap);
				splitter.setWidth(imageWidth);
				splitter.setHeight(h);
				splitter.setOverwrap(overwrap);
				if(!isSplitTypePixel){
					splitter.setMode(ImageSplitter.NUMBER_MODE);
					}
				splitter.setSplitNum(splitNum_value);
				splitter.setSupportDoubleSize(supportDouble);
				splitter.setDoubleSizeLimit(minDoubleSize);
				imageChanger=splitter;
				
			}else if(label.equals(Messages.getString("pspimage.turn"))){
				mode=TURN;
				imageWidth=toInt(splitWidthSize.getValue(),480);
				String tSize=turnSize.getValue();
				if(tSize!=null){
					int wh[]=FFMpegUtils.sizeToWidthHeight(tSize);
					imageWidth=wh[1];
					imageHeight=wh[0];
					
				}
				if(turnTypeRadio.getValue().equals("LEFT")){
					turnType_value=ImageTurner.TURN_LEFT;
				}else{
					turnType_value=ImageTurner.TURN_RIGHT;
				}
				
				ImageTurner turner=new ImageTurner();
				turner.setJpegQuality(jpegQuality);
				supportCancel=turner;
				
				turner.setWidth(imageWidth);
				turner.setHeight(imageHeight);
				turner.setTurnMode(turnType_value);
				
				imageChanger=turner;
			}else if(label.equals(Messages.getString("pspimage.fit_size"))){
				ImageResizer resizer=new ImageResizer();
				resizer.setJpegQuality(jpegQuality);
				
				String tSize=fitSizeSizeRadio.getValue();
				if(tSize!=null){
					int wh[]=FFMpegUtils.sizeToWidthHeight(tSize);
					imageWidth=wh[0];
					imageHeight=wh[1];
				}
				resizer.setWidth(imageWidth);
				resizer.setHeight(imageHeight);
				
				imageChanger=resizer;
			}else if(label.equals(Messages.getString("pspimage.fit_width"))){
				ImageResizer resizer=new ImageResizer();
				resizer.setJpegQuality(jpegQuality);
				
				imageWidth=toInt(fitWidthSizeRadio.getValue(),480);
				imageHeight=0;//
				
				resizer.setWidth(imageWidth);
				resizer.setHeight(imageHeight);
				
				imageChanger=resizer;
			}else if(label.equals(Messages.getString("pspimage.fit_height"))){
				ImageResizer resizer=new ImageResizer();
				resizer.setJpegQuality(jpegQuality);
				
				imageWidth=0;
				imageHeight=toInt(fitHeightSizeRadio.getValue(),480);
				
				resizer.setWidth(imageWidth);
				resizer.setHeight(imageHeight);
				
				imageChanger=resizer;
			}
			
			
			inputDirChooser_value=inputDirChooser.getAbsoluteFilePath();
			outputDirChooser_value=outputDirChooser.getAbsoluteFilePath();
			monitor=ProgressMonitorUtils.getProgressMonitor();
			
		}
		
		public int toInt(String text,int defaultValue){
			try{
				return Integer.parseInt(text);
			}catch(Exception e){
				return defaultValue;
			}
		}

		@Override
		public boolean canExecute() {
			return !inputDirChooser.getAbsoluteFilePath().equals("") && !outputDirChooser.getAbsoluteFilePath().equals("");
		}

		@Override
		public void cancelExecuting() {
			if(supportCancel!=null){
				supportCancel.setCancel(true);
			}
			cancelChange=true;
		}

		private boolean isConvertImage(String name){
			if(convertJpeg && ImageUtils.isJpegFile(name)){
				return true;
			}
			if(convertPng && ImageUtils.isPngFile(name)){
				return true;
			}
			if(convertGif && ImageUtils.isGifFile(name)){
				return true;
			}
			return false;
		}
		private void changeImages(File parentFile,String names[],File output){
			
			Arrays.sort(names);//sort for zipentries
			
			
			int folder=1;
			int psp_max1000=1000; //PSP max
			String baseName=output.getName();
		
			ZipFile zipFile=null;
			
			if(FileNameUtils.isZipFile(parentFile.getName())){
				try {
					zipFile=new ZipFile(parentFile);
					//log.info(Runtime.getRuntime().freeMemory()/1000);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		for (int i = 0; i < names.length; i++) {
			if(cancelChange){
				return;	//cancelld
			}
				try {
					String name=null;
					InputStream input=null;
					if(parentFile.isDirectory()){
						name=names[i];
						input=new FileInputStream(new File(parentFile,names[i]));
						
					}else{
						if(FileNameUtils.isZipFile(parentFile.getName())){
							name=names[i];
							ZipEntry entry=zipFile.getEntry(names[i]);
							input=zipFile.getInputStream(entry);
							
						}else{
							log.warn("not supported file:"+parentFile.getAbsolutePath());
						}
					}
					
					imageChanger.changeImage(name,input, output);
					
					try{
					input.close();
					}catch(Exception e){
						e.printStackTrace();
					}
					//current+=count;
				
					ProgressMonitorUtils.workedMonitor(monitor, 1);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		
		imageChanger.clear();
			//move folders
			File imageFiles[]=sortByLastModified(output,output.list());
			
			for (int i = 0; i < names.length; i++) {
				//log.info(imageFiles[i].getAbsolutePath());
			}
			
			
			//move over 1000 images to another folder because of psp limitation
			File moveTo=null;
			for(int i=psp_max1000;i<imageFiles.length;i++){
				if(i%psp_max1000==0){//create new dir
					moveTo=new File(output.getParent(),baseName+"["+folder+"]");//
					moveTo.mkdir();
					folder++;
				}
				boolean ret=imageFiles[i].renameTo(new File(moveTo,imageFiles[i].getName()));
				if(!ret){
					log.warn("rename faild:"+imageFiles[i]);
				}else{
					log.info("renamed:"+imageFiles[i]);
				}
			}
		}
		
		public File[] sortByLastModified(File parent,String list[]){
			if(list==null){
				return new File[0];
			}
			File files[]=new File[list.length];
			for (int i = 0; i < files.length; i++) {
				files[i]=new File(parent,list[i]);
			}
			Arrays.sort(files,new LastModofiedComparater());
			return files;
		}
		
		public class LastModofiedComparater implements Comparator<File>{

			public int compare(File file1, File file2) {
				// TODO Auto-generated method stub
				long t=file1.lastModified()-file2.lastModified();
				if(t<0){
					return -1;
				}else if(t>0){
					return 1;
				}else{
					return 0;
				}
			}
			
		}
		
		
		@Override
		public void inExecute() {
			Akj_betasPlugin.getDefault().startLogSession();
			System.gc();
			File input=new File(inputDirChooser_value);
			File outputParent=new File(outputDirChooser_value);
			if(!outputParent.exists()){
				StatusBarUtils.showStatusBar(Messages.getString("pspimage.dir_not_found"));
				
				return;
			}
			File output=null;
			String fileName=input.getName();
			if(input.isDirectory()){
				output=new File(FileNameUtils.getNotFoundFileName(new File(outputParent,input.getName())));
			}else if(ImageUtils.isImageFile(input.getAbsolutePath())){
				//use same as image.
				output=new File(FileNameUtils.getNotFoundFileName(new File(outputParent,FileNameUtils.getRemovedExtensionName(input.getName()))));
			}
				
			else if(FileNameUtils.isZipFile(input.getName())){
			
				//remove .zip .rar or other extensions.
				output=new File(FileNameUtils.getNotFoundFileName(new File(outputParent,FileNameUtils.getRemovedExtensionName(input.getName()))));
			}else{
				//unknow file;
				Akj_betasPlugin.getDefault().logPrintln(Messages.getString("pspimage.not_supported_file")+input.getName());
				return;
			}
		
			log.trace("mode:"+mode);
			
			List<String> imageNames=new ArrayList<String>();
			if(input.isDirectory()){
			String list[]=input.list();
			for (int i = 0; i < list.length; i++) {
				if(isConvertImage(list[i])){
					imageNames.add(list[i]);
					//log.infoadd:"+list[i]);
				}
			}
			}else{
				if(FileNameUtils.isZipFile(input.getName())){
					ZipFile zip;
					try {
						zip = new ZipFile(input);
					
					Enumeration en=zip.getEntries();
					while(en.hasMoreElements()){
						ZipEntry entry=(ZipEntry) en.nextElement();
						if(isConvertImage(entry.getName())){
							imageNames.add(entry.getName());
							//log.info(entry.getName());
						}
					}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}else{
					//image file;
					input=input.getParentFile();
					imageNames.add(fileName); //only one
				}
			}
			
			ProgressMonitorUtils.beginMonitor(monitor, Messages.getString("pspimage.start_convert"), imageNames.size());
			Akj_betasPlugin.getDefault().logPrintln(fileName+" "+imageNames.size()+" pictures");
			try{
			if(imageNames.size()>0){
				output.mkdir();
				changeImages(input,imageNames.toArray(new String[imageNames.size()]),output);
				Akj_betasPlugin.getDefault().logPrintln(Messages.getString("pspimage.convert_finished"));
				}else{
					StatusBarUtils.showStatusBar(Messages.getString("pspimage.empty_image"));	
				}
			}catch(Exception e){
				e.printStackTrace();
				StatusBarUtils.showStatusBar("faild_maybe_memory_error");
			}
			ProgressMonitorUtils.doneMonitor(monitor);
			
		}
		
		
	}

	public class FileSelected implements FileStatusChangeListener{

		public void addList(FileStatusChangeEvent event) {
			
			pspImageImportExecute.updateControlSwitch();
		}

		public void removeList(FileStatusChangeEvent event) {
			pspImageImportExecute.updateControlSwitch();
		}
		
	}

	

	
	
	String widgetKey=ID+"_widget";
	/**
	 * dont get value from widget directlly
	 * most of them are already disposed.
	 * @param key
	 */
	public void saveParameters(String key){
		//String csv=GenericParameters.mapToCsv(getParameters());
		//log.infosave-csv:"+csv);
		Akj_betasPlugin.getDefault().getPluginPreferences().setValue(key, paramCsvUpdater.getCsv());
	}
	public GenericParameters getDefaultParameters(){
		GenericParameters gm=new GenericParameters();
		
		//this time no default
		return null;
	}
	public void loadParameters(String key){
		String csv=Akj_betasPlugin.getDefault().getPluginPreferences().getString(key);
		GenericParameters gm=null;
		if(csv.equals("")){
			gm=getDefaultParameters();
		}else{
			gm=GenericParameters.csvToParameters(csv);
		}
		if(gm!=null){
			setParameters(gm.getParameters());
		}
	}
	
	public  Map<String,String> getParameters(){
		Map<String,String> parameterMap=new HashMap<String,String>();
		for (int i = 0; i < paramCsvUpdater.getParamList().size(); i++) {
			ParamItem item=paramCsvUpdater.getParamList().get(i);
			if(item.getValue().length()>0){
				parameterMap.put(item.getKey(), item.getValue());
			}
		}
		return parameterMap;
	}
	
	public void setParameters(Map map){
		for (int i = 0; i < paramCsvUpdater.getParamList().size(); i++) {
			ParamItem item=paramCsvUpdater.getParamList().get(i);
			String value=(String) map.get(item.getKey());
			if(value!=null){
				item.setValue(value);
			}else{
				item.setValue("");
			}
		}
	}
	
	

	public class ParamSaver implements IPartListener2{
		
		public void partActivated(IWorkbenchPartReference partRef) {
			
		}

		public void partBroughtToTop(IWorkbenchPartReference partRef) {
			
		}

		public void partClosed(IWorkbenchPartReference partRef) {
			
		}

		//take in here there are not so  time to take care of widget.
		public void partDeactivated(IWorkbenchPartReference partRef) {
			if(partRef.getId().equals(ID)){
				
				saveParameters(widgetKey);
				
			}
		}

		public void partHidden(IWorkbenchPartReference partRef) {
		}

		public void partInputChanged(IWorkbenchPartReference partRef) {
		}

		public void partOpened(IWorkbenchPartReference partRef) {
		}

		public void partVisible(IWorkbenchPartReference partRef) {
		}
		
	}
	
		
}